package com.tencent.shadow.sample.manager

import android.app.Service
import android.content.ComponentName
import android.content.Context
import android.content.Intent
import android.os.*
import android.util.Log
import android.view.LayoutInflater
import com.shadow.plugin_manager.R
import com.tencent.shadow.sample.manager.FastPluginManager
import com.tencent.shadow.dynamic.host.EnterCallback
import com.tencent.shadow.core.manager.installplugin.InstalledPlugin
import com.tencent.shadow.dynamic.loader.PluginServiceConnection
import com.tencent.shadow.sample.plugin.IMyAidlInterface
import java.lang.Exception
import java.lang.IllegalArgumentException
import java.lang.NullPointerException
import java.lang.RuntimeException
import java.util.concurrent.Executors

class SamplePluginManager(private val mCurrentContext: Context) : FastPluginManager(
    mCurrentContext
) {
    private val executorService = Executors.newSingleThreadExecutor()

    /**
     * @return PluginManager实现的别名，用于区分不同PluginManager实现的数据存储路径
     */
    override fun getName(): String {
        return "pp"
    }

    /**
     * @return 宿主中注册的PluginProcessService实现的类名
     */
    override fun getPluginProcessServiceName(): String {
        return "com.tencent.shadow.sample.introduce_shadow_lib.MainPluginProcessService"
    }

    override fun enter(context: Context, fromId: Long, bundle: Bundle, callback: EnterCallback) {
        if (fromId == Constant.FROM_ID_START_ACTIVITY.toLong()) {
            onStartActivity(context, bundle, callback)
        } else if (fromId == Constant.FROM_ID_CALL_SERVICE.toLong()) {
            callPluginService(context, bundle)
        } else {
            throw IllegalArgumentException("不认识的fromId==$fromId")
        }
    }

    private fun onStartActivity(context: Context, bundle: Bundle, callback: EnterCallback?) {
        val pluginZipPath = bundle.getString(Constant.KEY_PLUGIN_ZIP_PATH)
        val partKey = bundle.getString(Constant.KEY_PLUGIN_PART_KEY)
        val className = bundle.getString(Constant.KEY_ACTIVITY_CLASSNAME)
            ?: throw NullPointerException("className == null")
        val extras = bundle.getBundle(Constant.KEY_EXTRAS)
        if (callback != null) {
            val view =
                LayoutInflater.from(mCurrentContext).inflate(R.layout.activity_load_plugin, null)
            callback.onShowLoadingView(view)
        }
        executorService.execute {
            try {
                val installedPlugin = installPlugin(pluginZipPath, null, true) //这个调用是阻塞的
                val pluginIntent = Intent()
                pluginIntent.setClassName(
                    context.packageName,
                    className
                )
                if (extras != null) {
                    pluginIntent.replaceExtras(extras)
                }
                startPluginActivity(context, installedPlugin, partKey, pluginIntent)
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
            if (callback != null) {
                val uiHandler = Handler(Looper.getMainLooper())
                uiHandler.post {
                    callback.onCloseLoadingView()
                    callback.onEnterComplete()
                }
            }
        }
    }

    private fun callPluginService(context: Context, bundle: Bundle) {
        val pluginZipPath = bundle.getString(Constant.KEY_PLUGIN_ZIP_PATH)
        val partKey = bundle.getString(Constant.KEY_PLUGIN_PART_KEY)
        val className = bundle.getString(Constant.KEY_ACTIVITY_CLASSNAME)
            ?: throw NullPointerException("className == null")
        val pluginIntent = Intent()
        pluginIntent.setClassName(context.packageName, className)
        executorService.execute {
            try {
                val installedPlugin = installPlugin(pluginZipPath, null, true) //这个调用是阻塞的
                loadPlugin(installedPlugin.UUID, partKey)
                val pluginIntent = Intent()
                pluginIntent.setClassName(context.packageName, className)
                val callSuccess =
                    mPluginLoader.bindPluginService(pluginIntent, object : PluginServiceConnection {
                        override fun onServiceConnected(
                            componentName: ComponentName,
                            iBinder: IBinder
                        ) {
                            val iMyAidlInterface = IMyAidlInterface.Stub.asInterface(iBinder)
                            try {
                                val s = iMyAidlInterface.basicTypes(1, 2, true, 4.0f, 5.0, "6")
                                Log.i("SamplePluginManager", "iMyAidlInterface.basicTypes : $s")
                            } catch (e: RemoteException) {
                                throw RuntimeException(e)
                            }
                        }

                        override fun onServiceDisconnected(componentName: ComponentName) {
                            throw RuntimeException("onServiceDisconnected")
                        }
                    }, Service.BIND_AUTO_CREATE)
                if (!callSuccess) {
                    throw RuntimeException("bind service失败 className==$className")
                }
            } catch (e: Exception) {
                throw RuntimeException(e)
            }
        }
    }
}